package com.yy.weixinpay.controller;

import com.alipay.api.domain.StaffInfo;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.yy.weixinpay.service.WxPayService;
import com.yy.weixinpay.utils.HttpUtils;
import com.yy.weixinpay.utils.WechatPay2ValidatorForRequest;
import com.yy.weixinpay.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping("/api/wx-pay")
@CrossOrigin
@Api(tags = "微信支付接口")
public class WxPayController {
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private Verifier verifier;
    //发起支付
    @PostMapping("/native/{productId}")
    @ApiOperation("发起支付，生成支付二维码")
    public R nativePay(@PathVariable Long productId){
        log.info("发起支付，生成一个支付二维码");
        Map<String,Object> map = null;
        try {
            map = wxPayService.nativePay(productId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return R.ok().setData(map);
    }

    //回调函数，接受微信的异步通知，要把通知结果通知给我们
    @PostMapping("/native/notify")
    @ApiOperation("接受微信通知的异步方法")
    public String notify(HttpServletRequest request,HttpServletResponse response) throws InterruptedException {
        log.info("接收订单异步通知");
        Map<String,Object> m = new HashMap<>();
        try{
            log.info("接收微信的异步通知");

            String body = HttpUtils.readData(request);
            log.info("微信的通知结果:{}",body);
            Gson gson = new Gson();
            Map<String,Object> map = gson.fromJson(body, Map.class);
            Object id = map.get("id");
            log.info("支付通知的id:{}",id);

            //  验签 保证是微信发过来的
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest =
                    new WechatPay2ValidatorForRequest(verifier, (String) id, body);
            //验签
            if (!wechatPay2ValidatorForRequest.validate(request)){
                log.info("验签失败");
                m.put("code","ERROR");
                m.put("message","验签失败");
                return  gson.toJson(m);
            }
            log.info("验签成功");

            // TODO: 2023/11/29 处理订单
            //对密文解密
            wxPayService.processOrder(map);

            response.setStatus(200);

            m.put("code","SUCCESS");
            m.put("message","成功");
            String s = gson.toJson(m);
            return  s;
        }catch (Exception e){
            Gson gson = new Gson();
            response.setStatus(200);
            m.put("code","ERROR");
            m.put("message","失败");
            return  gson.toJson(m);
        }
    }


    //取消订单操作
    @PostMapping("/cancel/{orderNo}")
    public R cancel(@PathVariable String orderNo){
        log.info("取消订单：{}",orderNo);
        wxPayService.cancelOrder(orderNo);
        return R.ok().setMessage("取消订单成功");
    }

    //主动查询订单
    @GetMapping("/query/{orderNo}")
    @ApiOperation("主动查单")
    public  R query(@PathVariable String orderNo){
        log.info("查询订单");
        String result = wxPayService.queryOrder(orderNo);
        return R.ok().setMessage("查询订单成功").data("result",result);
    }

    //申请退款
    @ApiOperation("申请退款")
    @PostMapping("/refunds/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo,@PathVariable String reason){
        log.info("申请退款,商品号:{},退款原因：{}",orderNo,reason);
        wxPayService.refund(orderNo,reason);
        return R.ok();
    }

    //退款结果通知
    @PostMapping("/refunds/notify")
    public String refundNotify(HttpServletRequest request,HttpServletResponse response){
        log.info("退款通知执行");
        Gson gson = new Gson();
        Map<String,Object> responseMap = new HashMap<>();
        try{
            //处理通知参数
            String body = HttpUtils.readData(request);
            HashMap<String,Object> bodyMap = gson.fromJson(body, HashMap.class);
            String id = (String) bodyMap.get("id");
            log.info("退款通知的id：{}",id);
            //验签
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier,id,body);
            if (!wechatPay2ValidatorForRequest.validate(request)){
                log.error("通知验签失败");
                response.setStatus(500);
                responseMap.put("code","ERROR");
                responseMap.put("message","通知验签失败");
                return gson.toJson(responseMap);
            }
            log.info("验签成功");
            //处理退款订单
            wxPayService.processRefund(bodyMap);
            response.setStatus(200);
            responseMap.put("code","SUCCESS");
            responseMap.put("message","成功");
            return gson.toJson(responseMap);
        }catch (Exception e){
            e.printStackTrace();
            response.setStatus(500);
            responseMap.put("code","ERROR");
            return gson.toJson(responseMap);
        }

    }


    /**
     * 查询退款
     */
    @ApiOperation("查询退款：")
    @GetMapping("/query-refund/{refundNo}")
    public R queryRefund(@PathVariable String refundNo){
        log.info("查询退款");
        String result = wxPayService.queryRefund(refundNo);
        return R.ok().setMessage("查询成功").data("result",result);
    }

    /**
     * 获取账单
     * @param billDate
     * @param type
     * @return
     */
    @ApiOperation("获取账单url")
    @GetMapping("/querybill/{billDate}/{type}")
    public R queryTradeBill(@PathVariable String billDate,@PathVariable String type){
        log.info("获取账单");
        String downloadUrl = wxPayService.queryBill(billDate,type);
        return R.ok().setMessage("获取账单成功").data("downloadUrl",downloadUrl);
    }

    @ApiOperation("下载账单")
    @GetMapping("/downloadbill/{billDate}/{type}")
    public R downloadBill(@PathVariable String billDate,@PathVariable String type){
        log.info("下载账单");
        String result = wxPayService.downloadBill(billDate,type);
        return R.ok().data("result",result);
    }
}
